home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / DIZZY / SRC / SIMMEM.C < prev    next >
Text File  |  1990-12-29  |  7KB  |  314 lines

  1. /*
  2. >>    Dizzy 1.0
  3. >>
  4. >>    A digital circuit simulator & design program for the X Window System
  5. >>
  6. >>    Copyright 1990 Juri Munkki, all rights reserved
  7. >>
  8. >>    Please read the included file called "DizzyDoc" for information on
  9. >>    what your rights are concerning this product.
  10. */
  11.  
  12. #include    "dizzy.h"
  13.  
  14. #ifdef    MACINTOSH
  15. #include    <stdlib.h>    /*    malloc & realloc!    */
  16. #else
  17. extern char *malloc();    /*    no malloc & realloc .h-file found in our unix machines. */
  18. extern char *realloc();
  19. #endif
  20.  
  21. /*
  22. >>    This function allocates "request" bytes and returns
  23. >>    a pointer (of type Element *) to the caller. Memory
  24. >>    is allocated in RAMCHUNK sized chunks to keep things
  25. >>    faster. Only a few pointers are globally kept pointing
  26. >>    to things inside the allocated memory. These pointers
  27. >>    should be fixed to point at the correct location after
  28. >>    resize. You should be very careful with pointers that
  29. >>    are stored in local variables. Avoid them whenever you
  30. >>    can. (Especially recursive functions are dangerous.)
  31. */
  32. Element     *SimAllocate(request)
  33. long    request;
  34. {
  35.     long    SimBaseOffset,CurHeaderOffset,MainHeaderOffset;
  36.  
  37.     while(SimEnd+request > SimSize)     /*    Do we have insufficient memory preallocated?    */
  38.     {    SimSize+=RAMCHUNK;                /*    Increase to previous size+RAMCHUNK.             */
  39.         SimBaseOffset=SimBase-SimPtr;    /*    Since realloc and SetHandleSize probably move    */
  40.         CurHeaderOffset=((Ptr) CurHeader)-SimPtr;    /*    the memory block, we can't assume    */
  41.         MainHeaderOffset=((Ptr) MainHeader)-SimPtr; /*    that pointers will be valid after    */
  42.                                                     /*    the operation. Store as offsets.    */
  43. #ifdef    MACINTOSH
  44.         HUnlock(SimHandle);
  45.         SetHandleSize(SimHandle,SimSize);
  46.         HLock(SimHandle);
  47.         SimPtr= *SimHandle;
  48. #else
  49.         SimPtr=realloc(SimPtr,SimSize);
  50. #endif
  51.         SimBase=SimPtr+SimBaseOffset;    /*    Restore offsets into pointer form.                */
  52.         CurHeader=(TableHeader *)(SimPtr+CurHeaderOffset);
  53.         MainHeader=(TableHeader *)(SimPtr+MainHeaderOffset);
  54.     }
  55.     
  56.     SimEnd+=request;
  57.     
  58.     return    (Element *)(SimPtr+SimEnd-request);
  59. }
  60.  
  61. /*
  62. >>    This could almost be a macro. It just converts a pointer into the
  63. >>    current data (pointed by SimBase) into an offset.
  64. */
  65. long    PtrToOffset(pt)
  66. void    *pt;
  67. {
  68.     return ((char *)pt)-SimBase;
  69. }
  70.  
  71. /*
  72. >>    The Chip component of an input structure is stored either
  73. >>    as a memory offset or a number. This converts indices to
  74. >>    memory offsets. Used with garbage collection and file operations.
  75. */
  76. void    IndexToOffset()
  77. {
  78.                 long        count;
  79.     register    long        offs;
  80.                 int         i;
  81.     register    Element     *elem;
  82.     register    Input        *ip;
  83.                 long        *table;
  84.  
  85.     count=0;
  86.  
  87.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  88.     {    elem=(Element *)(SimBase+offs);
  89.         if(elem->Number>count)
  90.             count=elem->Number;
  91.     }
  92.  
  93. #ifdef    MACINTOSH
  94.     table=(long *)NewPtr(sizeof(long)*count);
  95. #else
  96.     table=(long *)malloc(sizeof(long)*count);
  97. #endif
  98.  
  99.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  100.     {    elem=(Element *)(SimBase+offs);
  101.         table[elem->Number-1]=offs;
  102.     }
  103.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  104.     {    elem=(Element *)(SimBase+offs);
  105.         ip=(Input *)(&elem->Out[elem->Outputs]);
  106.         
  107.         for(i=0;i<elem->Inputs;i++)
  108.         {    if(ip->Chip<=0 || ip->Chip>count)
  109.             {    ip->Chip=0;
  110.                 ip->Pin=0;
  111.             }
  112.             else
  113.             {    ip->Chip=table[ip->Chip-1];
  114.                 if(ip->Pin>((Element *)(SimBase+ip->Chip))->Outputs)
  115.                 {    ip->Chip=0;
  116.                     ip->Pin=0;
  117.                 }
  118.             }
  119.             ip++;
  120.         }
  121.     }
  122. #ifdef    MACINTOSH
  123.     DisposPtr(table);
  124. #else
  125.     free(table);
  126. #endif
  127. }
  128. /*
  129. >>    This program assigns numbers to elements. The number is stored
  130. >>    in the Number component of the element.
  131. */
  132. void    AssignNumbers()
  133. {
  134.     int     count;
  135.     long    offs;
  136.     Element *elem;
  137.     
  138.     count=0;
  139.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  140.     {    elem=(Element *)(SimBase+offs);
  141.         elem->Number= ++count;
  142.     }
  143. }
  144. /*
  145. >>    This does the reverse of what IndexToOffset does. If you wish to
  146. >>    move components around in memory, first convert offsets to indices
  147. >>    and then do the moving. After you are through, convert back to
  148. >>    offset form, since that is what dizzy mostly expects to have.
  149. */
  150. void    OffsetToIndex()
  151. {
  152.     int     i;
  153.     Input    *ip;
  154.     long    offs;
  155.     Element *elem,*source;
  156.     
  157.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  158.     {    elem=(Element *)(SimBase+offs);
  159.         ip=(Input *)&elem->Out[elem->Outputs];
  160.         for(i=0;i<elem->Inputs;i++)
  161.         {    if(ip->Chip)
  162.             {    source=(Element *)(SimBase+ip->Chip);
  163.                 ip->Chip=source->Number;
  164.             }
  165.             ip++;
  166.         }
  167.     }
  168.     
  169. }
  170. /*
  171. >>    Do garbage collection. Removes any ZAPP type elements from
  172. >>    the database.
  173. */
  174. void    DatabaseCleanup()
  175. {
  176.     int     count;
  177.     long    offs,len,i;
  178.     Element *elem;
  179.     char    *source,*dest;
  180.  
  181.     AssignNumbers();
  182.     OffsetToIndex();
  183.     
  184.     source=SimBase+MainHeader->First;
  185.     dest=source;
  186.  
  187.     for(offs=MainHeader->First;offs<MainHeader->Last;offs+=len)
  188.     {    elem=(Element *)(SimPtr+offs);
  189.         len=elem->Length;
  190.         if(elem->Type==ZAPP)
  191.         {    source+=len;
  192.         }
  193.         else
  194.         {    i=len;
  195.             while(i-- > 0)
  196.             {    *dest++= *source++;
  197.             }
  198.         }
  199.     }
  200.     MainHeader->Last=dest-SimBase;
  201.     SimEnd=MainHeader->Last;
  202.     IndexToOffset();
  203. }
  204. /*
  205. >>    This creates a new element with ins inputs, outs outputs
  206. >>    a type of obtype and a body width of width. This routine
  207. >>    can be used for most standard components. The connector
  208. >>    type is an exception.
  209. */
  210. Element *CreateNewElement(ins,outs,obtype,width)
  211. int     ins,outs;
  212. long    obtype;
  213. int     width;
  214. {
  215.     register    long        esize;
  216.     register    Element     *newel;
  217.     register    Input        *ip;
  218.                 int         i;
  219.                 Point        spot;
  220.  
  221.     esize=sizeof(Element)+ins*sizeof(Input)+(outs-1)*sizeof(Output);
  222.     newel=SimAllocate(esize);
  223.     newel->Flags=0;
  224.     newel->Type=obtype;
  225.     newel->Length=esize;
  226.     newel->Inputs=ins;
  227.     newel->Outputs=outs;
  228.     
  229.     ip=(Input *)&(newel->Out[outs]);
  230.     for(i=0;i<outs;i++)
  231.     {    newel->Out[i].Data=0;
  232.     }
  233.     for(i=0;i<ins;i++)
  234.     {    ip->Chip=0;
  235.         ip->Pin=0;
  236.         ip++;
  237.     }
  238.     
  239.     GetMouseDownPoint(&spot);
  240.     spot.h &= ~7;
  241.     spot.v &= ~7;
  242.     PresetElement(newel,spot.h,spot.v,width);
  243.     
  244.     return newel;
  245. }
  246. /*
  247. >>    Since you can't create a new connector with CreateNewElement,
  248. >>    you can at least use this routine to initialize some of the
  249. >>    fields in the struct.
  250. */
  251. void    InitConnector(elem,x,y)
  252. Element *elem;
  253. int     x,y;
  254. {
  255.     elem->Flags=0;
  256.     elem->Type=CONN;
  257.     elem->Length=sizeof(Element)+sizeof(Input);
  258.     elem->Inputs=1;
  259.     elem->Outputs=1;
  260.     SetRect(&elem->Body,x-4,y-4,x+5,y+5);
  261.     elem->OutRect=NilRect;
  262.     elem->InRect=NilRect;        
  263. }
  264. /*
  265. >>    Count how many types "obtype" occurs on this level of the
  266. >>    database. Useful for counting ZAPPs and in CUSTom chips.
  267. */
  268. int CountElementType(obtype)
  269. long    obtype;
  270. {
  271.     long    offs;
  272.     Element *elem;
  273.     int     count=0;
  274.     
  275.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  276.     {    elem=(Element *)(SimBase+offs);
  277.         if(elem->Type==obtype)
  278.         {    count++;
  279.         }
  280.     }
  281.     return count;
  282. }
  283. /*
  284. >>    This allocates some memory for starters and
  285. >>    creates the main level header of the database.
  286. >>    It also sets up the simulation speed of the program
  287. >>    and resets the clock counter.
  288. */
  289. void    SimSetup()
  290. {
  291.     SimSize=RAMCHUNK;
  292.  
  293. #ifdef    MACINTOSH
  294.     SimHandle=NewHandle(SimSize);    
  295.     HLock(SimHandle);
  296.  
  297.     SimPtr= *SimHandle;
  298. #else
  299.     SimPtr=malloc(SimSize);
  300. #endif
  301.  
  302.     SimEnd=0;
  303.  
  304.     MainHeader=(TableHeader *)SimAllocate(sizeof(TableHeader));
  305.     MainHeader->XOrig=1;
  306.     MainHeader->YOrig=1;
  307.     MainHeader->First=SimEnd;
  308.     MainHeader->Last=SimEnd;
  309.     SimBase=SimPtr;
  310.     CurHeader=MainHeader;
  311.     SimTimer=0;
  312.     SimSpeed=0; /*    Start out at maximum speed. */
  313. }
  314.